package com.jumi.microservice.service.order;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.bean.ProducerBean;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jumi.microservice.common.base.dto.BaseRequest;
import com.jumi.microservice.common.base.dto.BaseResponse;
import com.jumi.microservice.common.base.dto.ResponseResult;
import com.jumi.microservice.common.constant.DelFlag;
import com.jumi.microservice.common.constant.ImageResizeEnum;
import com.jumi.microservice.common.exception.BaseException;
import com.jumi.microservice.common.page.TableDataInfo;
import com.jumi.microservice.common.utils.DateUtil;
import com.jumi.microservice.common.utils.EnumUtil;
import com.jumi.microservice.common.utils.ImageResizeUtil;
import com.jumi.microservice.config.TimeConfiguration;
import com.jumi.microservice.constant.PayChannelEnum;
import com.jumi.microservice.constant.compensation.AfterSaleStatusEnum;
import com.jumi.microservice.domain.*;
import com.jumi.microservice.dto.PaymentRequest;
import com.jumi.microservice.dto.WaitCommentGoods;
import com.jumi.microservice.dto.WaitCommentRequest;
import com.jumi.microservice.dto.WaitCommentResponse;
import com.jumi.microservice.dto.invoice.InvoiceStatusRequest;
import com.jumi.microservice.dto.logistics.AutoSpiltRequest;
import com.jumi.microservice.dto.order.*;
import com.jumi.microservice.dto.pay.OrderPayListResponse;
import com.jumi.microservice.dto.reponse.AddressResponse;
import com.jumi.microservice.dto.reponse.PurchaseLimitActivityDTO;
import com.jumi.microservice.dto.reponse.UserExternalResponse;
import com.jumi.microservice.dto.shoppingcart.ShoppingCartGoodsResponse;
import com.jumi.microservice.dto.shoppingcart.ShoppingCartListRequest;
import com.jumi.microservice.dto.shoppingcart.ShoppingCartRequest;
import com.jumi.microservice.dto.shoppingcart.ShoppingCartResponse;
import com.jumi.microservice.entity.OrderGoods;
import com.jumi.microservice.entity.OrderLog;
import com.jumi.microservice.entity.UserOrder;
import com.jumi.microservice.entity.UserShoppingCart;
import com.jumi.microservice.enumerate.*;
import com.jumi.microservice.mapper.OrderGoodsMapper;
import com.jumi.microservice.mapper.OrderLogMapper;
import com.jumi.microservice.mapper.UserOrderMapper;
import com.jumi.microservice.mapper.UserShoppingCartMapper;
import com.jumi.microservice.order.context.OrderCreateContext;
import com.jumi.microservice.order.factory.BuyProductPipelineFactory;
import com.jumi.microservice.order.pipeline.TransOutboundInvoker;
import com.jumi.microservice.rocketmq.RocketMqConfig;
import com.jumi.microservice.rocketmq.SendMessageHandler;
import com.jumi.microservice.service.*;
import com.jumi.microservice.service.logistics.AutoSpiltService;
import com.jumi.microservice.service.logistics.admin.SendService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author Dirk
 * @Date 2020-07-07 18:16
 */
@DubboService(interfaceClass = IOrderDubboService.class)
@RefreshScope
public class OrderDubboServiceImpl implements IOrderDubboService {

    private static final Logger log = LoggerFactory.getLogger(OrderDubboServiceImpl.class);

    @Resource
    private BuyProductPipelineFactory buyProductPipelineFactory;

    @DubboReference
    private IPayService payService;

    @Resource
    private UserOrderMapper userOrderMapper;

    @Resource
    private OrderGoodsMapper orderGoodsMapper;

    @Resource
    private OrderLogMapper orderLogMapper;

    @Resource
    private UserShoppingCartMapper userShoppingCartMapper;

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    @DubboReference
    private IOrderInventoryService orderInventoryService;

    @DubboReference
    private BasicDataService basicDataService;

    @Resource
    private SendService sendService;

    @DubboReference
    private IAddressService addressService;

    @Resource
    AutoSpiltService autoSpiltService;

    @DubboReference
    private IWalletInvoiceService walletInvoiceService;
    @DubboReference
    private GorderActivityApi gorderActivityApi;

    @Resource
    ProducerBean producerBean;
    @Autowired
    RocketMqConfig rocketMqConfig;

    @Resource
    SendMessageHandler sendMessageHandler;

    @DubboReference
    private IUserExternalService userExternalService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    TimeConfiguration timeConfiguration;

    /**
     * 确认订单
     *
     * @param createOrderRequest
     * @return
     */
    @Override
    public ConfirmOrderResponse confirmOrder(CreateOrderRequest createOrderRequest) {
        ConfirmOrderResponse confirmOrderResponse = new ConfirmOrderResponse();
        // 收件人信息
        AddressResponse addressResponse = addressService.getAddressById(createOrderRequest.getReceiverId());
        if (addressResponse == null) {
            addressResponse = addressService.getDefaultAddressByUid(createOrderRequest.getUid().intValue());
        }
        if (addressResponse != null) {
            confirmOrderResponse.setTrueName(addressResponse.getTrueName());
            confirmOrderResponse.setMobPhone(addressResponse.getMobPhone());
            confirmOrderResponse.setAddress(addressResponse.getAreaInfo().concat(" ").concat(addressResponse.getAddress()));
            confirmOrderResponse.setAddressId(addressResponse.getAddressId());
        }
        long areaId = addressResponse == null ? 0L : addressResponse.getProvinceId().longValue();

        Map<Integer, Integer> goodsMap = createOrderRequest.getGoodsList()
                .stream().collect(Collectors.toMap(GoodsSkuRequest::getGoodsId, GoodsSkuRequest::getGoodsAmount));

        // 获取商品详情
        List<Long> skuIds = createOrderRequest.getGoodsList()
                .stream()
                .map(GoodsSkuRequest::getGoodsId)
                .map(Integer::longValue)
                .collect(Collectors.toList());
        // 尝试从redis获取商品详情
        List<String> skuIdsKey = skuIds.stream().map(skuId -> "JUMI:SKU:".concat(skuId.toString())).collect(Collectors.toList());
        List<Object> skuList = redisTemplate.opsForValue().multiGet(skuIdsKey);
        List<SkuDTO> skuDTOList = new ArrayList<>();
        if (!ObjectUtils.isEmpty(skuList)) {
            skuDTOList = skuList.stream().filter(Objects::nonNull).map(o -> (SkuDTO) o).collect(Collectors.toList());
        }
        // 将redis没有的sku通过服务调用获取
        List<Long> subSkuIds = skuDTOList.stream().map(SkuDTO::getId).collect(Collectors.toList());
        skuIds.removeAll(subSkuIds);
        skuDTOList.addAll(new ArrayList<>(basicDataService.getSkuInfoByIds(skuIds).values()));

        if (!skuDTOList.isEmpty() && skuDTOList.get(0).getIsImport() == 1) {
            //获取该用户最后一次输入的身份证号跟真实姓名
            QueryWrapper<UserOrder> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("buyer_id", createOrderRequest.getUid())
                    .isNotNull("imp_card_no").orderByDesc("create_time").last(" limit 1");
            UserOrder userOrder = userOrderMapper.selectOne(queryWrapper);
            confirmOrderResponse.setImpRealName(userOrder == null ? "" : userOrder.getImpRealName());
            confirmOrderResponse.setImpCardNo(userOrder == null ? "" : userOrder.getImpCardNo());
        }

        // 拆单
        List<SkuDTO> subList = new ArrayList<>();
        Iterator<SkuDTO> iterator = skuDTOList.iterator();
        while (iterator.hasNext()) {
            SkuDTO skuDTO = iterator.next();
            if (skuDTO.getGoodsType() == 2) {
                // 第三方商品
                subList.add(skuDTO);
                iterator.remove();
            }
        }
        List<ConfirmOrderResponse> confirmOrderResponseList = new ArrayList<>();
        if (!skuDTOList.isEmpty()) {
            confirmOrderResponseList.add(getConfirmOrderResponse(skuDTOList, areaId, goodsMap));
        }
        if (!subList.isEmpty()) {
            Set<Long> supplyIds = subList.stream().map(SkuDTO::getSupplyId).collect(Collectors.toSet());
            supplyIds.forEach(supplyId -> {
                List<SkuDTO> subSkuDTOList = subList.stream()
                        .filter(skuDTO -> skuDTO.getSupplyId().equals(supplyId))
                        .collect(Collectors.toList());
                confirmOrderResponseList.add(getConfirmOrderResponse(subSkuDTOList, areaId, goodsMap));
            });
        }
        confirmOrderResponse.setGoodsGroups(confirmOrderResponseList);
        confirmOrderResponse.setNoDeliveryRegion(confirmOrderResponseList.stream()
                .map(ConfirmOrderResponse::getNoDeliveryRegion)
                .filter(Boolean::booleanValue)
                .findFirst()
                .orElse(false)
        );

        // 用户角色
        UserExternalResponse user = userExternalService.getUserByUid(createOrderRequest.getUid().intValue());
        confirmOrderResponse.setRole(user.getLevel());
        return confirmOrderResponse;
    }


    private ConfirmOrderResponse getConfirmOrderResponse(List<SkuDTO> skuDTOList, long areaId, Map<Integer, Integer> goodsMap) {
        ConfirmOrderResponse confirmOrder = new ConfirmOrderResponse();
        List<ConfirmOrderGoodsResponse> confirmOrderGoodsResponseList = new ArrayList<>();
        skuDTOList.forEach(skuDTO -> {
            ConfirmOrderGoodsResponse goods = new ConfirmOrderGoodsResponse();
            BeanUtils.copyProperties(skuDTO, goods);
            goods.setMaxLimitAmount(0);
            //redis 取最大限购数量
            Boolean hasKey = redisTemplate.hasKey("PurchaseLimitActivity::".concat(skuDTO.getGoodsId().toString()));
            if (hasKey != null && hasKey) {
                PurchaseLimitActivityDTO purchaseLimitActivityDTO = (PurchaseLimitActivityDTO) redisTemplate.opsForValue()
                        .get("PurchaseLimitActivity::".concat(skuDTO.getGoodsId().toString()));
                log.info("最大限购数据 [{}]", purchaseLimitActivityDTO.getAmount());
                goods.setMaxLimitAmount(purchaseLimitActivityDTO.getAmount());
            }
            goods.setGoodsPropertyImage(ImageResizeUtil.imageResize(skuDTO.getGoodsPropertyImage(), ImageResizeEnum.LIST));
            goods.setGoodsSpec(skuDTO.getSpecName());
            if (areaId != 0) {
                goods.setFreightFee(getGoodsFreightFee(skuDTO.getFreightTempDTO(), Long.toString(areaId),
                        skuDTO.getGoodsGrossWeight().multiply(new BigDecimal(goodsMap.get(skuDTO.getId().intValue()))),
                        goodsMap.get(skuDTO.getId().intValue())));
                String noDeliveryRegion = skuDTO.getNoDeliveryRegion();
                if (!ObjectUtils.isEmpty(noDeliveryRegion)) {
                    if (noDeliveryRegion.contains(Long.toString(areaId))) {
                        confirmOrder.setNoDeliveryRegion(true);
                    }
                }
            } else {
                goods.setFreightFee(BigDecimal.ZERO);
            }
            goods.setGoodsAmount(goodsMap.get(skuDTO.getId().intValue()));
            confirmOrderGoodsResponseList.add(goods);
        });
        confirmOrder.setGoodsList(confirmOrderGoodsResponseList);
        return confirmOrder;
    }


    /**
     * 创建订单
     *
     * @param createOrderRequest
     * @return
     */
    @Override
    public CreateOrderResponse createOrder(CreateOrderRequest createOrderRequest) {
        TransOutboundInvoker invoker = buyProductPipelineFactory.build(createOrderRequest);
        invoker.start();
        OrderCreateContext context = invoker.getContext();
        // 删除购物车
        if (new Byte("1").equals(createOrderRequest.getShoppingCartFlag())) {
            ShoppingCartListRequest shoppingCartListRequest = new ShoppingCartListRequest();
            shoppingCartListRequest.setGoodsIds(createOrderRequest.getGoodsList().stream()
                    .map(GoodsSkuRequest::getGoodsId).collect(Collectors.toList()));
            shoppingCartListRequest.setUid(createOrderRequest.getUid());
            deleteShoppingCart(shoppingCartListRequest);
        }

        CreateOrderResponse response = new CreateOrderResponse();
        response.setPayNo(context.getPayNo());
        context.getGoodsList().forEach(c -> response.setFreeGoods(c.getFreeGoods()));
        response.setAmount(context.getOrderPromotionAmount().add(context.getFreightFee()));
        response.setPayAmount(context.getPayAmount());
        response.setCreateTime(new Date());
        response.setRemainSeconds((DateUtil.getDateAfterMinute(response.getCreateTime(), 30).getTime()
                - System.currentTimeMillis()) / 1000);
        return response;
    }

    /**
     * 支付订单
     *
     * @param request
     * @return
     */
    @Override
    public BaseResponse payment(BaseRequest request) {
        PaymentRequest paymentRequest = (PaymentRequest) request;
        String payNo = paymentRequest.getPaymentSn();
        QueryWrapper<UserOrder> userOrderQw = new QueryWrapper<>();
        userOrderQw.eq("pay_no", payNo);
        userOrderQw.eq("order_status", OrderStatusEnum.READY_TO_PAY.getCode());
        List<UserOrder> userOrderList = userOrderMapper.selectList(userOrderQw);
        if (userOrderList.isEmpty()) {
            // paymentSn兼容订单编号
            userOrderQw = new QueryWrapper<>();
            userOrderQw.eq("order_no", payNo);
            userOrderQw.eq("order_status", OrderStatusEnum.READY_TO_PAY.getCode());
            UserOrder userOrder = userOrderMapper.selectOne(userOrderQw);
            if (userOrder != null) {
                // 修改支付单号为订单编号
                userOrder.setPayNo(userOrder.getOrderNo());
                userOrderMapper.updateById(userOrder);
                userOrderList.add(userOrder);
            }
        }
        if (userOrderList.isEmpty()) {
            throw new BaseException(500, "待支付订单不存在");
        }

        // 修改支付渠道
        UserOrder userOrder = new UserOrder();
        userOrder.setPayType(paymentRequest.getPayChannel().getCode());
        userOrderMapper.update(userOrder, userOrderQw);

        // 计算订单金额
        BigDecimal totalAmount = userOrderList.stream()
                .map(UserOrder::getPayAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        paymentRequest.setTotalAmount(totalAmount);
        if ("".equals(paymentRequest.getSubject())) {
            paymentRequest.setSubject("支付方式:" + paymentRequest.getPayChannel().getDescription());
        }
        log.info("支付参数:[{}]", paymentRequest.toString());
        return payService.execPay(paymentRequest);
    }

    /**
     * 取消订单
     *
     * @param request
     * @return
     */
    @Override
    @Transactional
    public Boolean cancel(OrderInfoRequest request) {
        QueryWrapper<UserOrder> userOrderQw = new QueryWrapper<>();
        userOrderQw.eq("buyer_id", request.getUid());
        userOrderQw.eq("order_no", request.getOrderSn());
        UserOrder userOrder = userOrderMapper.selectOne(userOrderQw);
        if (userOrder == null) {
            return false;
        }
        if (!OrderStatusEnum.READY_TO_PAY.getCode().equals(userOrder.getOrderStatus())) {
            return false;
        }
        QueryWrapper<OrderGoods> orderGoodsQw = new QueryWrapper<>();
        orderGoodsQw.eq("order_id", userOrder.getId());
        List<OrderGoods> orderGoodsList = orderGoodsMapper.selectList(orderGoodsQw);
        // 取消库存
        orderGoodsList.forEach(goods -> {
            OrderItemDTO orderItem = new OrderItemDTO();
            orderItem.setStockLogId(Long.parseLong(goods.getWarehouseSn()));
            orderItem.setPurchaseQuantity(goods.getGoodsAmount());
            orderItem.setIsPre(userOrder.getOrderType().equals(OrderTypeEnum.PRE_SALE_CREATE.getCode()) ? 1 : 0);
            orderItem.setIsShelf(goods.getSelfFlag().intValue());
            orderItem.setActualWarehouseId(goods.getRealWarehouse().longValue());
            orderItem.setGoodsSkuId(goods.getGoodsId().longValue());
            orderItem.setOrderNo(userOrder.getOrderNo());
            log.info("取消订单时解除库存锁定: [{}]", JSON.toJSONString(orderItem));
            Boolean b = orderInventoryService.informCancelOrderEvent(orderItem);
            log.info("取消订单时解除库存锁定 结果: [{}]", b);
        });

        OrderGoods orderGoods = new OrderGoods();
        orderGoods.setGoodsStatus(LogisticsStatusEnum.CANCEL.getCode());
        orderGoodsMapper.update(orderGoods, orderGoodsQw);
        // 修改订单状态
        userOrder.setOrderStatus(OrderStatusEnum.CANCEL.getCode());
        int row = userOrderMapper.updateById(userOrder);
        // 发送推送消息
        MessageTemplate messageTemplate = sendMessageHandler.getMessageTemplate(3);
        String appMessageContent = messageTemplate == null ? "" : messageTemplate.getSmtAppContent();
        String stationMessageContent = messageTemplate == null ? "" : messageTemplate.getSmtMessageContent();
        sendMessageHandler.sendMessage(userOrder.getOrderNo(), appMessageContent, stationMessageContent,
                "", "", "", orderGoodsList.get(0).getGoodsCoverImg(),
                userOrder.getBuyerId(), 3, BigDecimal.ZERO, BigDecimal.ZERO, "", (byte) 0);
        return row > 0;
    }

    /**
     * 获取订单详情(分页)
     *
     * @param request
     * @return
     */
    @Override
    public TableDataInfo<OrderResponse> getOrderInfoPage(OrderInfoRequest request) {
        TableDataInfo<OrderResponse> tableDataInfo = new TableDataInfo<>();
        QueryWrapper<UserOrder> userOrderQw = new QueryWrapper<>();
        userOrderQw.eq("buyer_id", request.getUid());
        userOrderQw.eq("del_flag", DelFlag.NORMAL);
        if (request.getOrderStatus() != null) {
            userOrderQw.eq("order_status", request.getOrderStatus());
        }
        if (!StringUtils.isEmpty(request.getOrderSn())) {
            userOrderQw.eq("order_no", request.getOrderSn());
        }
        userOrderQw.orderByDesc("id");
        IPage<UserOrder> userOrderPage = new Page<>(request.getPageNum(), request.getPageSize());
        userOrderPage = userOrderMapper.selectPage(userOrderPage, userOrderQw);
        tableDataInfo.setTotal(userOrderPage.getTotal());
        tableDataInfo.setRows(getOrderResponseList(userOrderPage.getRecords()));
        return tableDataInfo;
    }

    /**
     * 获取订单详情(全部)
     *
     * @param request
     * @return
     */
    @Override
    public List<OrderResponse> getOrderInfoList(OrderInfoRequest request) {
        QueryWrapper<UserOrder> userOrderQw = new QueryWrapper<>();
        userOrderQw.eq("buyer_id", request.getUid());
        userOrderQw.eq("del_flag", DelFlag.NORMAL);
        userOrderQw.orderByDesc("id");
        if (request.getOrderStatus() != null) {
            userOrderQw.eq("order_status", request.getOrderStatus());
        }
        List<UserOrder> userOrderList = userOrderMapper.selectList(userOrderQw);
        return getOrderResponseList(userOrderList);
    }

    /**
     * 搜索我的订单列表(分页)
     *
     * @param request
     * @return
     */
    @Override
    public TableDataInfo<OrderResponse> getOrderInfoSearch(OrderInfoRequest request) {
        if (request.getSearchKeyword() == null) {
            return getOrderInfoPage(request);
        }
        QueryWrapper<UserOrder> userOrderQw = new QueryWrapper<>();
        userOrderQw.eq("buyer_id", request.getUid());
        userOrderQw.eq("del_flag", DelFlag.NORMAL);
        List<UserOrder> userOrderList = userOrderMapper.selectList(userOrderQw);
        if (userOrderList.isEmpty()) {
            return new TableDataInfo<>();
        }
        TableDataInfo<OrderResponse> tableDataInfo = new TableDataInfo<>();
        List<Integer> orderIds = userOrderList.stream().map(UserOrder::getId).collect(Collectors.toList());
        QueryWrapper<OrderGoods> orderGoodsQw = new QueryWrapper<>();
        orderGoodsQw.in("order_id", orderIds);
        orderGoodsQw.like("goods_name", "%".concat(request.getSearchKeyword()).concat("%"));
        List<OrderGoods> orderGoodsList = orderGoodsMapper.selectList(orderGoodsQw);
        if (orderGoodsList.isEmpty()) {
            return new TableDataInfo<>();
        }
        List<Integer> subOrderIds = orderGoodsList.stream().map(OrderGoods::getOrderId).collect(Collectors.toList());
        QueryWrapper<UserOrder> searchUserOrderQw = new QueryWrapper<>();
        searchUserOrderQw.in("id", subOrderIds);
        searchUserOrderQw.orderByDesc("create_time");
        IPage<UserOrder> userOrderPage = new Page<>(request.getPageNum(), request.getPageSize());
        userOrderPage = userOrderMapper.selectPage(userOrderPage, searchUserOrderQw);
        tableDataInfo.setTotal(userOrderPage.getTotal());
        tableDataInfo.setRows(getOrderResponseList(userOrderPage.getRecords()));
        return tableDataInfo;
    }

    /**
     * 获取订单详情(私有方法)
     *
     * @param userOrderList
     * @return
     */
    private List<OrderResponse> getOrderResponseList(List<UserOrder> userOrderList) {
        List<OrderResponse> orderResponseList = new ArrayList<>();
        if (userOrderList.isEmpty()) {
            return orderResponseList;
        }
        List<Integer> orderIds = userOrderList.stream().map(UserOrder::getId).collect(Collectors.toList());
        QueryWrapper<OrderGoods> orderGoodsQw = new QueryWrapper<>();
        orderGoodsQw.in("order_id", orderIds);
        List<OrderGoods> orderGoodsList = orderGoodsMapper.selectList(orderGoodsQw);

        userOrderList.forEach(userOrder -> {
            if (userOrder.getOrderStatus().equals(OrderStatusEnum.READY_TO_PAY.getCode()) &&
                    DateUtil.getDateAfterMinute(userOrder.getCreateTime(), 15).before(new Date())) {
                // 超时未支付取消订单
                OrderInfoRequest orderInfoRequest = new OrderInfoRequest();
                orderInfoRequest.setOrderSn(userOrder.getOrderNo());
                orderInfoRequest.setUid(userOrder.getBuyerId());
                cancel(orderInfoRequest);
                userOrder.setOrderStatus(OrderStatusEnum.CANCEL.getCode());
            }
            OrderResponse orderResponse = new OrderResponse();
            BeanUtils.copyProperties(userOrder, orderResponse);
            long remainSeconds = (userOrder.getFailureTime().getTime() - System.currentTimeMillis()) / 1000;
            orderResponse.setRemainSeconds(remainSeconds > 0 ? remainSeconds : 0);
            orderResponse.setPayChannel(userOrder.getPayType());
            orderResponse.setRemarks(userOrder.getRemark());
            List<OrderGoods> subOrderGoodsList = orderGoodsList.stream()
                    .filter(orderGoods -> orderGoods.getOrderId().equals(userOrder.getId()))
                    .collect(Collectors.toList());
            List<GoodsSkuResponse> goodsSkuResponses = new ArrayList<>();
            subOrderGoodsList.forEach(orderGoods -> {
                GoodsSkuResponse goodsSkuResponse = new GoodsSkuResponse();
                BeanUtils.copyProperties(orderGoods, goodsSkuResponse);
                goodsSkuResponse.setGoodsCoverImg(ImageResizeUtil
                        .imageResize(goodsSkuResponse.getGoodsCoverImg(), ImageResizeEnum.LIST));
                goodsSkuResponses.add(goodsSkuResponse);
            });
            orderResponse.setGoodsList(goodsSkuResponses);
            // 订单售后状态
            orderResponse.setAfterSealStatus(getOrderAfterSaleStatus(userOrder, subOrderGoodsList));
            // 发票ID
            orderResponse.setInvoiceId(walletInvoiceService.invoiceOneStatus(userOrder.getId()));
            orderResponse.setOrderId(userOrder.getId());
            orderResponseList.add(orderResponse);
        });
        return orderResponseList;
    }

    /**
     * 订单售后状态
     *
     * @param userOrder
     * @param orderGoodsList
     * @return 0 不显示 1 申请售后 2 售后详情
     */
    private Byte getOrderAfterSaleStatus(UserOrder userOrder, List<OrderGoods> orderGoodsList) {
        if (userOrder.getConfirmTime() == null
                || DateUtil.getDateAfterMinute(userOrder.getConfirmTime(),
                Integer.parseInt(timeConfiguration.getAfterSaleMinutes())).after(new Date())) {
            OrderGoods afterSaleGoods = orderGoodsList.stream()
                    .filter(orderGoods -> !isAfterSale(orderGoods))
                    .findFirst().orElse(null);
            if (afterSaleGoods != null) {
                // 在售后期内且存在可售后商品(可售后指未在前台发起售后)
                return new Byte("1");
            }
        }
        OrderGoods afterSaleGoods = orderGoodsList.stream()
                .filter(this::isAfterSale)
                .findFirst().orElse(null);
        if (afterSaleGoods != null) {
            // 含有售后过的商品
            return new Byte("2");
        }
        // 不显示申请售后和售后详情按钮
        return new Byte("0");
    }

    /**
     * 前台是否发起售后
     *
     * @param orderGoods
     * @return
     */
    private Boolean isAfterSale(OrderGoods orderGoods) {
        return orderGoods.getAfterSealStatus().equals(AfterSaleStatusEnum.REFUND.getCode().byteValue())
                || orderGoods.getAfterSealStatus().equals(AfterSaleStatusEnum.REFUND_GOODS_APPLY.getCode().byteValue())
                || orderGoods.getAfterSealStatus().equals(AfterSaleStatusEnum.REFUND_GOODS_AGREE.getCode().byteValue())
                || orderGoods.getAfterSealStatus().equals(AfterSaleStatusEnum.REFUND_GOODS_REFUSE.getCode().byteValue());
    }

    /**
     * 批量发货
     *
     * @param request
     * @return
     */
    @Override
    public Boolean deliverGoods(DeliverGoodsRequest request) {
        if (request.getOrderIds().isEmpty()) {
            return true;
        }
        QueryWrapper<UserOrder> userOrderQw = new QueryWrapper<>();
        userOrderQw.in("id", request.getOrderIds());
        userOrderQw.eq("order_status", OrderStatusEnum.READY_TO_SHIP.getCode());
        UserOrder userOrder = new UserOrder();
        userOrder.setOrderStatus(OrderStatusEnum.READY_TO_RECEIVE.getCode());
        int rows = userOrderMapper.update(userOrder, userOrderQw);
        return rows > 0;
    }

    /**
     * 添加订单日志
     *
     * @param request
     * @return
     */
    @Override
    public Boolean addOrderLog(OrderLogRequest request) {
        OrderLog orderLog = new OrderLog();
        BeanUtils.copyProperties(request, orderLog);
        int rows = orderLogMapper.insert(orderLog);
        return rows > 0;
    }

    /**
     * 查询订单日志
     *
     * @param orderSn
     * @return
     */
    @Override
    public List<OrderLogResponse> getOrderLogList(String orderSn) {
        QueryWrapper<OrderLog> orderLogQw = new QueryWrapper<>();
        orderLogQw.eq("order_sn", orderSn);
        orderLogQw.orderByDesc("id");
        List<OrderLog> orderLogList = orderLogMapper.selectList(orderLogQw);
        List<OrderLogResponse> responseList = new ArrayList<>();
        orderLogList.forEach(orderLog -> {
            OrderLogResponse response = new OrderLogResponse();
            BeanUtils.copyProperties(orderLog, response);
            responseList.add(response);
        });
        return responseList;
    }

    /**
     * 添加购物车
     *
     * @param request
     * @return
     */
    @Override
    public Boolean addShoppingCart(ShoppingCartRequest request) {
        QueryWrapper<UserShoppingCart> userShoppingCartQw = new QueryWrapper<>();
        userShoppingCartQw.eq("uid", request.getUid());
        userShoppingCartQw.eq("goods_id", request.getGoodsId());
        userShoppingCartQw.eq("del_flag", DelFlag.NORMAL);
        UserShoppingCart userShoppingCart = userShoppingCartMapper.selectOne(userShoppingCartQw);

        List<Long> skuIdList = new ArrayList<>();
        skuIdList.add(request.getGoodsId().longValue());
        List<SkuDTO> goodsSkuInfoList = basicDataService.getGoodsSkuListByIds(skuIdList);
        log.info("添加购物车时获取商品属性:[{}]", JSON.toJSONString(goodsSkuInfoList));
        if (goodsSkuInfoList.isEmpty()) {
            return false;
        }
        log.info("判断海外商品结果 [{}]", goodsSkuInfoList.get(0).getIsImport() != null && goodsSkuInfoList.get(0).getIsImport() == 1);
        if (goodsSkuInfoList.get(0).getIsImport() != null && goodsSkuInfoList.get(0).getIsImport() == 1) {
            throw new BaseException(600, "当前商品为海外商品，暂时无法加入购物车，请直接购买。");
        }
        if (goodsSkuInfoList.get(0).getInvalid()) {
            throw new BaseException(600, "当前商品已失效，暂时无法加入购物车。");
        }
        //获取spu
        List<Long> spuId = goodsSkuInfoList.stream().map(SkuDTO::getGoodsId).collect(Collectors.toList());
        //活动商品
        List<Long> activityGoodsIds = gorderActivityApi.goodsActivityType4Order(spuId);
        activityGoodsIds.forEach(
                activityGoodsId -> {
                    if (activityGoodsId.equals(spuId.get(0))) {
                        throw new BaseException(600, "当前商品为活动中商品，暂时无法加入购物车，请直接购买。");
                    }
                }
        );
        log.info("活动商品spu ids: [{}]", JSON.toJSONString(activityGoodsIds));

        if (userShoppingCart == null) {
            if (request.getAmount() < 0) {
                return false;
            }
            userShoppingCart = new UserShoppingCart();
            userShoppingCart.setUid(request.getUid());
            userShoppingCart.setGoodsId(request.getGoodsId());
            userShoppingCart.setAmount(request.getAmount());
            return userShoppingCartMapper.insert(userShoppingCart) > 0;
        } else {
            int amount = userShoppingCart.getAmount() + request.getAmount();
            if (request.getIsReselectAmount() != null && request.getIsReselectAmount().equals((byte) 1)) {
                amount = request.getAmount();
            }
            if (amount > goodsSkuInfoList.get(0).getSaleStockQuantity()) {
                throw new BaseException(500, "库存不足");
            }
            userShoppingCart.setAmount(amount > 0 ? amount : 1);
            return userShoppingCartMapper.updateById(userShoppingCart) > 0;
        }
    }

    /**
     * 批量添加购物车
     *
     * @param request
     * @return
     */
    @Override
    public Boolean addShoppingCart(ShoppingCartListRequest request) {
        List<Integer> goodsIds = request.getGoodsIds();
        if (goodsIds.isEmpty()) {
            return false;
        }
        for (Integer goodsId : goodsIds) {
            ShoppingCartRequest shoppingCartRequest = new ShoppingCartRequest();
            shoppingCartRequest.setUid(request.getUid());
            shoppingCartRequest.setGoodsId(goodsId);
            shoppingCartRequest.setAmount(1);
            boolean res = addShoppingCart(shoppingCartRequest);
            if (!res) {
                return res;
            }
        }
        return true;
    }

    /**
     * 购物车列表
     *
     * @param uid
     * @return
     */
    @Override
    public ShoppingCartResponse getShoppingCart(Integer uid) {
        QueryWrapper<UserShoppingCart> userShoppingCartQw = new QueryWrapper<>();
        userShoppingCartQw.eq("uid", uid);
        userShoppingCartQw.orderByDesc("id");
        List<UserShoppingCart> userShoppingCartList = userShoppingCartMapper.selectList(userShoppingCartQw);
        List<Long> skuIdList = userShoppingCartList.stream()
                .map(UserShoppingCart::getGoodsId)
                .map(Integer::longValue)
                .collect(Collectors.toList());
        List<SkuDTO> goodsSkuInfoList = basicDataService.getGoodsSkuListByIds(skuIdList);
        List<Long> spuId = goodsSkuInfoList.stream().map(SkuDTO::getGoodsId).collect(Collectors.toList());
        log.debug("购物车详情返回参数: [{}]", JSON.toJSONString(goodsSkuInfoList));
        List<ShoppingCartGoodsResponse> shoppingCart = new ArrayList<>();
        List<ShoppingCartGoodsResponse> shoppingCartInvalid = new ArrayList<>();
        //活动商品的spuId
        List<Long> activityGoodsId = gorderActivityApi.goodsActivityType4Order(spuId);
        log.debug("活动商品spu ids: [{}]", JSON.toJSONString(activityGoodsId));
        userShoppingCartList.forEach(userShoppingCart -> {
            ShoppingCartGoodsResponse response = new ShoppingCartGoodsResponse();
            SkuDTO skuDTO = goodsSkuInfoList.stream()
                    .filter(sku -> sku.getId().equals(userShoppingCart.getGoodsId().longValue()))
                    .findFirst().orElse(new SkuDTO());
            BeanUtils.copyProperties(skuDTO, response);
            response.setGoodsPropertyImage(ImageResizeUtil.imageResize(skuDTO.getGoodsPropertyImage(), ImageResizeEnum.LIST));
            response.setShoppingCartId(userShoppingCart.getId());
            response.setAmount(userShoppingCart.getAmount());
            if (skuDTO.getInvalid()) {
                shoppingCartInvalid.add(response);
            } else {
                if (activityGoodsId.contains(skuDTO.getGoodsId())) {
                    response.setGoodsStatus(1);
                    shoppingCartInvalid.add(response);
                } else {
                    shoppingCart.add(response);
                }
            }
        });
        ShoppingCartResponse response = new ShoppingCartResponse();
        response.setShoppingCart(shoppingCart);
        response.setShoppingCartInvalid(shoppingCartInvalid);
        return response;
    }

    /**
     * 批量删除购物车
     *
     * @param request
     * @return
     */
    @Override
    public Boolean deleteShoppingCart(ShoppingCartListRequest request) {
        QueryWrapper<UserShoppingCart> userShoppingCartQw = new QueryWrapper<>();
        userShoppingCartQw.eq("uid", request.getUid());
        userShoppingCartQw.in("goods_id", request.getGoodsIds());
        return userShoppingCartMapper.delete(userShoppingCartQw) > 0;
    }

    /**
     * 修改购物车商品
     *
     * @param request
     * @return
     */
    @Override
    public Boolean changeShoppingCartSku(ShoppingCartRequest request) {
        QueryWrapper<UserShoppingCart> userShoppingCartQw = new QueryWrapper<>();
        userShoppingCartQw.eq("uid", request.getUid());
        userShoppingCartQw.eq("goods_id", request.getGoodsId());
        UserShoppingCart userShoppingCart = userShoppingCartMapper.selectOne(userShoppingCartQw);
        if (userShoppingCart != null) {
            if (userShoppingCart.getId().equals(request.getShoppingCartId())) {
                return true;
            }
            userShoppingCart.setAmount(userShoppingCart.getAmount() + request.getAmount());
            userShoppingCartMapper.deleteById(request.getShoppingCartId());
        } else {
            userShoppingCart = new UserShoppingCart();
            userShoppingCart.setId(request.getShoppingCartId());
            userShoppingCart.setUid(request.getUid());
            userShoppingCart.setGoodsId(request.getGoodsId());
            userShoppingCart.setAmount(request.getAmount());
        }
        return userShoppingCartMapper.updateById(userShoppingCart) > 0;
    }

    /**
     * 统计各个状态的订单数量
     *
     * @param request
     * @return
     */
    @Override
    public Integer countUserOrder(UserOrderRequest request) {
        QueryWrapper<UserOrder> userOrderQw = new QueryWrapper<>();
        userOrderQw.eq("buyer_id", request.getUid());
        userOrderQw.eq("del_flag", DelFlag.NORMAL);
        if (request.getOrderStatus() != null) {
            userOrderQw.eq("order_status", request.getOrderStatus());
        }
        return userOrderMapper.selectCount(userOrderQw);
    }

    /**
     * 预售单转实际
     *
     * @return
     */
    @Override
    @Transactional
    public Boolean changeOrderType(ChangeOrderTypeRequest request) {
        List<OrderGoodsRequest> orderGoodsRequestList = request.getOrderGoodsList();
        if (ObjectUtils.isEmpty(orderGoodsRequestList)) {
            return false;
        }
        // 查询预售单
        QueryWrapper<UserOrder> userOrderQw = new QueryWrapper<>();
        userOrderQw.eq("order_type", OrderTypeEnum.PRE_SALE_CREATE.getCode());
        userOrderQw.eq("order_status", OrderStatusEnum.READY_TO_SHIP.getCode());
        List<UserOrder> userOrderList = userOrderMapper.selectList(userOrderQw);
        if (userOrderList.isEmpty()) {
            return false;
        }
        List<Integer> orderIds = userOrderList.stream().map(UserOrder::getId).collect(Collectors.toList());
        // 查询预售商品
        QueryWrapper<OrderGoods> orderGoodsQw = new QueryWrapper<>();
        orderGoodsQw.and(orderGoodsQueryWrapper ->
                orderGoodsRequestList.forEach(orderGoodsRequest ->
                        orderGoodsQueryWrapper.or().eq("goods_id", orderGoodsRequest.getSkuId())
                )
        );
        orderGoodsQw.and(orderGoodsQueryWrapper -> orderGoodsQueryWrapper.in("order_id", orderIds));
        List<OrderGoods> orderGoodsList = orderGoodsMapper.selectList(orderGoodsQw);
        // 库存准换
        OrderWareStockDTO orderWareStockDTO = new OrderWareStockDTO();
        List<OrderGoodsSkuWareDTO> orderGoodsSkuWares = new ArrayList<>();
        List<OrderReplenishDTO> orderReplenishes = new ArrayList<>();
        orderGoodsRequestList.forEach(orderGoodsRequest -> {
            OrderGoodsSkuWareDTO orderGoodsSkuWareDTO = new OrderGoodsSkuWareDTO();
            orderGoodsSkuWareDTO.setSkuId(orderGoodsRequest.getSkuId().longValue());
            orderGoodsSkuWareDTO.setWareId(orderGoodsRequest.getWarehouseId().longValue());
            orderGoodsSkuWareDTO.setAddStock(orderGoodsRequest.getAmount());
            orderGoodsSkuWares.add(orderGoodsSkuWareDTO);
        });
        orderGoodsList.forEach(orderGoods -> {
            OrderReplenishDTO orderReplenishDTO = new OrderReplenishDTO();
            UserOrder userOrder = userOrderList.stream()
                    .filter(order -> order.getId().equals(orderGoods.getOrderId()))
                    .findFirst().orElse(null);
            if (userOrder == null) {
                return;
            }
            orderReplenishDTO.setOrderSn(userOrder.getOrderNo());
            orderReplenishDTO.setSkuId(orderGoods.getGoodsId().longValue());
            orderReplenishDTO.setStorage(orderGoods.getGoodsAmount());
            orderReplenishes.add(orderReplenishDTO);
        });
        orderWareStockDTO.setOrderGoodsSkuWares(orderGoodsSkuWares);
        orderWareStockDTO.setOrderReplenishes(orderReplenishes);
        log.info("预售转实际扣库存请求参数: [{}]", JSON.toJSONString(orderWareStockDTO));
        ResponseResult<List<OrderReplenishDTO>> responseResult = orderInventoryService.preSaleOrderEvent(orderWareStockDTO);
        List<OrderReplenishDTO> orderReplenishDTOList = responseResult.getData();
        log.info("预售转实际扣库存返回: [{}]", JSON.toJSONString(orderReplenishDTOList));
        if (orderReplenishDTOList.isEmpty()) {
            return false;
        }
        List<String> orderSnList = orderReplenishDTOList.stream()
                .map(OrderReplenishDTO::getOrderSn).collect(Collectors.toList());
        userOrderQw = new QueryWrapper<>();
        userOrderQw.in("order_no", orderSnList);
        UserOrder userOrder = new UserOrder();
        userOrder.setOrderType(OrderTypeEnum.USER_CREATE.getCode());
        int rows = userOrderMapper.update(userOrder, userOrderQw);
        orderGoodsMapper.batchUpdateRealWarehouseByOrderNo(orderReplenishDTOList);
        //自动拆单
        if (!orderSnList.isEmpty()) {
            for (String orderNo : orderSnList) {
                AutoSpiltRequest autoSpiltRequest = new AutoSpiltRequest();
                autoSpiltRequest.setOrderNo(orderNo);
                autoSpiltService.autoSpiltOrder(autoSpiltRequest);
            }
        }
        return rows > 0;
    }


    /**
     * spu 销量
     *
     * @param salesRequest
     * @return
     */
    @Override
    public SalesResponse getSpuSalesVolume(SalesRequest salesRequest) {
        List<Integer> spuIds = salesRequest.getSpuIds().stream().map(Long::intValue).collect(Collectors.toList());
        List<Map<String, Object>> spuSalesVolumeMapList = orderGoodsMapper.getSpuSalesVolume(
                spuIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
        List<SalesSpuResponse> salesSpuList = new ArrayList<>();
        spuSalesVolumeMapList.forEach(map -> {
            SalesSpuResponse response = new SalesSpuResponse();
            response.setSpuId(Long.valueOf(map.get("spu_id").toString()));
            response.setSalesVolume(Integer.valueOf(map.get("sales_volume").toString()));
            salesSpuList.add(response);
        });
        SalesResponse response = new SalesResponse();
        response.setSalesSpuList(salesSpuList);
        return response;
    }

    /**
     * 确认收货接口
     *
     * @param request
     * @return
     */
    @Override
    @Transactional
    public Boolean confirmReceipt(OrderInfoRequest request) {
        QueryWrapper<UserOrder> userOrderQw = new QueryWrapper<>();
        userOrderQw.eq("buyer_id", request.getUid());
        userOrderQw.eq("order_no", request.getOrderSn());
        userOrderQw.eq("order_status", OrderStatusEnum.READY_TO_RECEIVE.getCode());
        UserOrder userOrder = userOrderMapper.selectOne(userOrderQw);
        if (userOrder == null) {
            return true;
        }
        //确认订单商品收货
        QueryWrapper<OrderGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", userOrder.getId()).eq("del_flag", 0);
        List<OrderGoods> orderGoodsList = orderGoodsMapper.selectList(queryWrapper);
        Set<Byte> set = orderGoodsList.stream().map(OrderGoods::getGoodsStatus).collect(Collectors.toSet());
        if (set.contains(LogisticsStatusEnum.WAIT_SEND.getCode()) || set.contains(LogisticsStatusEnum.PART_SEND.getCode())) {
            throw new BaseException(600, "由于订单商品未完全发货，暂时无法确认收货，给您带来不便，敬请谅解。");
        }
        // 修改订单状态
        userOrder.setOrderStatus(OrderStatusEnum.COMPLETED.getCode());
        userOrder.setConfirmTime(new Date());
        int row = userOrderMapper.updateById(userOrder);
        for (OrderGoods orderGoods : orderGoodsList) {
            orderGoods.setGoodsStatus(LogisticsStatusEnum.CONFIRM_RECEIVE.getCode());
            orderGoodsMapper.updateById(orderGoods);
        }
        //修改包裹状态
        sendService.confirmReceive(userOrder.getOrderNo());

        try {
            // 修改发票状态
            InvoiceStatusRequest invoiceStatusRequest = new InvoiceStatusRequest();
            invoiceStatusRequest.setOrderNum(userOrder.getOrderNo());
            invoiceStatusRequest.setInvoiceStatus(InvoiceStatusEnum.STA_WAIT_BILLED.getCode().byteValue());
            log.info("修改发票请求参数[{}]", JSON.toJSONString(invoiceStatusRequest));
            walletInvoiceService.invoiceEditStatus(invoiceStatusRequest);
        } catch (Exception e) {
            log.error("开票出错 [{}]", e.getMessage());
        }

        // 添加日志
        OrderLogRequest orderLogRequest = new OrderLogRequest();
        orderLogRequest.setOperatorId(request.getUid());
        orderLogRequest.setUserFlag(new Byte("1"));
        orderLogRequest.setOperatorName("买家");
        orderLogRequest.setOrderSn(request.getOrderSn());
        orderLogRequest.setLog("确认收货");
        addOrderLog(orderLogRequest);

        //发送确认收货订单队列
        Message message = new Message("orderAccomplish", "", "", JSONObject.toJSONBytes(userOrder));
        //TODO 正式部署要解开
        message.setStartDeliverTime(DateUtil.getDateAfterMinute(userOrder.getConfirmTime(),
                Integer.parseInt(timeConfiguration.getSettlementMinutes())).getTime());
        producerBean.send(message);
        log.info("确认收货发送消息队列 订单编号[{}]", JSON.toJSONString(userOrder));
        return row > 0;
    }

    /**
     * 软删除订单
     *
     * @param request
     * @return
     */
    @Override
    public Boolean deleteOrder(OrderInfoRequest request) {
        QueryWrapper<UserOrder> userOrderQw = new QueryWrapper<>();
        userOrderQw.eq("buyer_id", request.getUid());
        userOrderQw.eq("order_no", request.getOrderSn());
        userOrderQw.eq("del_flag", DelFlag.NORMAL);
        UserOrder userOrder = userOrderMapper.selectOne(userOrderQw);
        if (userOrder == null) {
            return true;
        }
        userOrder.setDelFlag(DelFlag.DELETE);
        int row = userOrderMapper.updateById(userOrder);
        return row > 0;
    }

    /**
     * 前台待评价订单列表
     *
     * @return
     */
    @Override
    public TableDataInfo<WaitCommentResponse> waitCommentList(WaitCommentRequest request) {
        TableDataInfo tableDataInfo = new TableDataInfo();
        List<WaitCommentResponse> result = new ArrayList<>();
        //获取该用户待评价订单
        IPage<UserOrder> page = new Page<>(request.getPageNum(), request.getPageSize());
        IPage<UserOrder> userOrderPages = userOrderMapper.waitCommentOrder(request.getUid(), page);
        List<UserOrder> userOrders = userOrderPages.getRecords();
        if (userOrders.isEmpty()) {
            tableDataInfo.setTotal(0L);
            tableDataInfo.setRows(result);
            return tableDataInfo;
        }
        List<Integer> ids = userOrders.stream().map(UserOrder::getId).collect(Collectors.toList());
        QueryWrapper<OrderGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("create_time").in("order_id", ids);
        List<OrderGoods> orderGoodsList = orderGoodsMapper.selectList(queryWrapper);
        Map<String, List<WaitCommentGoods>> goodsMap = new HashMap<>();
        for (OrderGoods orderGoods : orderGoodsList) {
            WaitCommentGoods waitCommentGoods = new WaitCommentGoods();
            BeanUtils.copyProperties(orderGoods, waitCommentGoods);
            waitCommentGoods.setGoodsCoverImg(ImageResizeUtil.imageResize(orderGoods.getGoodsCoverImg(), ImageResizeEnum.LIST));
            if (goodsMap.containsKey(orderGoods.getOrderNo())) {
                goodsMap.get(orderGoods.getOrderNo()).add(waitCommentGoods);
                continue;
            }
            List<WaitCommentGoods> list = new ArrayList<>();
            list.add(waitCommentGoods);
            goodsMap.put(orderGoods.getOrderNo(), list);
        }
        for (UserOrder userOrder : userOrders) {
            WaitCommentResponse waitCommentResponse = new WaitCommentResponse();
            waitCommentResponse.setOrderNo(userOrder.getOrderNo());
            waitCommentResponse.setList(goodsMap.get(userOrder.getOrderNo()));
            result.add(waitCommentResponse);
        }
        tableDataInfo.setTotal(userOrderPages.getTotal());
        tableDataInfo.setRows(result);
        return tableDataInfo;
    }

    /**
     * 待评价订单数量
     *
     * @return
     */
    @Override
    public Integer waitCommentCount(Long uid) {
        //获取该用户所有订单
        IPage<UserOrder> page = new Page<>(1, 10);
        IPage<UserOrder> iPage = userOrderMapper.waitCommentOrder(uid, page);
        return Integer.parseInt(String.valueOf(iPage.getTotal()));
    }

    /**
     * 获取商品运费
     *
     * @param freightTempDTO   运费模版
     * @param areaId           省级地区id，默认全国使用0
     * @param goodsGrossWeight 商品总重量
     * @param goodsAmount      商品总数量
     * @return
     */
    @Override
    public BigDecimal getGoodsFreightFee(Object freightTempDTO, String areaId, BigDecimal goodsGrossWeight, Integer goodsAmount) {
        FreightTempDTO freightTemp = (FreightTempDTO) freightTempDTO;
        List<FreightTempInfoDTO> info = freightTemp.getInfo();
        if (info.isEmpty()) {
            throw new BaseException(500, "获取运费模板失败");
        }
        FreightTempInfoDTO freightTempInfo = info.stream()
                .filter(freightTempInfoDTO -> freightTempInfoDTO.getTopAreaId().contains(areaId))
                .findFirst().orElse(null);
        if (freightTempInfo == null) {
            freightTempInfo = info.stream()
                    .filter(freightTempInfoDTO -> "0".equals(freightTempInfoDTO.getTopAreaId()))
                    .findFirst().orElseThrow(() -> new BaseException(500, "获取运费模板失败"));
        }
        if (freightTemp.getRule() == null) {
            throw new BaseException(500, "获取运费模板失败");
        }
        if (freightTemp.getRule() == 0) {
            goodsAmount -= freightTempInfo.getSnum();
            if (goodsAmount <= 0) {
                return freightTempInfo.getSprice();
            }
            if (freightTempInfo.getXnum() <= 0) {
                throw new BaseException(500, "运费模板异常");
            }
            BigDecimal multiple = new BigDecimal(goodsAmount).divide(new BigDecimal(freightTempInfo.getXnum()), 0, BigDecimal.ROUND_CEILING);
            return freightTempInfo.getSprice().add(freightTempInfo.getXprice().multiply(multiple));
        } else if (freightTemp.getRule() == 1) {
            goodsGrossWeight = goodsGrossWeight.subtract(freightTempInfo.getSweight());
            if (goodsGrossWeight.compareTo(BigDecimal.ZERO) < 1) {
                return freightTempInfo.getSwprice();
            }
            if (freightTempInfo.getXweight().equals(BigDecimal.ZERO)) {
                throw new BaseException(500, "运费模板异常");
            }
            BigDecimal multiple = goodsGrossWeight.divide(freightTempInfo.getXweight(), 0, BigDecimal.ROUND_CEILING);
            return freightTempInfo.getSwprice().add(freightTempInfo.getXwprice().multiply(multiple));
        } else {
            throw new BaseException(500, "未知的运费模板");
        }
    }

    /**
     * 获取用户一段时间内spu购买数量
     *
     * @return
     */
    @Override
    public List<ActivityUserSalesRequest> getSpuSalesVolumeActivity(List<ActivityUserSalesRequest> requestList) {
        if (requestList.isEmpty()) {
            return requestList;
        }
        // 用户全部订单
        QueryWrapper<UserOrder> userOrderQw = new QueryWrapper<>();
        userOrderQw.eq("buyer_id", requestList.get(0).getUid());
        userOrderQw.ne("order_status", OrderStatusEnum.CANCEL.getCode());
        List<UserOrder> userOrderList = userOrderMapper.selectList(userOrderQw);
        if (userOrderList.isEmpty()) {
            requestList.forEach(request -> {
                request.setOrderNum(0);
                request.setBuyNum(0);
            });
            return requestList;
        }
        List<Integer> orderIds = userOrderList.stream().map(UserOrder::getId).collect(Collectors.toList());

        // 用户未支付订单
        QueryWrapper<UserOrder> userReadyToPayOrderQw = new QueryWrapper<>();
        userReadyToPayOrderQw.eq("buyer_id", requestList.get(0).getUid());
        userReadyToPayOrderQw.eq("order_status", OrderStatusEnum.READY_TO_PAY.getCode());
        List<UserOrder> userReadyToPayOrderList = userOrderMapper.selectList(userReadyToPayOrderQw);
        List<Integer> userReadyToPayOrderIds = userReadyToPayOrderList.stream()
                .map(UserOrder::getId).collect(Collectors.toList());

        // 订单商品查询
        List<OrderGoods> orderGoodsList = new ArrayList<>();
        requestList.forEach(request -> {
            OrderGoods orderGoods = new OrderGoods();
            orderGoods.setSpuId(request.getSpuId().intValue());
            orderGoods.setCreateTime(request.getDate());
            orderGoods.setActivityId(request.getActivityId());
            orderGoods.setActivityType(request.getActivityType());
            orderGoodsList.add(orderGoods);
        });
        List<Map<String, Object>> spuSalesVolumeMapList = orderGoodsMapper.getSpuSalesVolumeByUidInDate(
                orderGoodsList,
                orderIds.stream().map(String::valueOf).collect(Collectors.joining(",")));

        spuSalesVolumeMapList.forEach(map -> requestList.stream()
                .filter(request -> request.getSpuId().equals(Long.valueOf(map.get("spu_id").toString())))
                .findFirst()
                .ifPresent(sales -> {
                    sales.setBuyNum(Integer.valueOf(map.get("order_count").toString()));
                    sales.setOrderNum(Integer.valueOf(map.get("sales_volume").toString()));
                    if (sales.getBuyNum() != 0 && !userReadyToPayOrderIds.isEmpty()) {
                        QueryWrapper<OrderGoods> orderGoodsQw = new QueryWrapper<>();
                        orderGoodsQw.eq("spu_id", sales.getSpuId());
                        orderGoodsQw.eq("activity_id", sales.getActivityId());
                        orderGoodsQw.eq("activity_type", sales.getActivityType());
                        orderGoodsQw.in("order_id", userReadyToPayOrderIds);
                        orderGoodsQw.eq("del_flag", DelFlag.NORMAL);
                        sales.setNoPayBuyNum(orderGoodsMapper.selectCount(orderGoodsQw));
                    } else {
                        sales.setNoPayBuyNum(0);
                    }
                })
        );
        log.debug("活动商品获取销量返回: [{}]", JSON.toJSONString(requestList));
        return requestList;
    }

    @Value("${pay.type}")
    private String payType;

    @Override
    public ResponseResult<List<OrderPayListResponse>> getPayType(Integer clientType) {
        ResponseResult<List<OrderPayListResponse>> responseResult = new ResponseResult<>();
        List<OrderPayListResponse> result = new ArrayList<>();
        if (clientType == null || clientType == 0) {
            clientType = ClientTypeEnum.APP_CLIENT.getCode();
        }
        List<String> allowPayType = Arrays.asList(payType.split("[;；,，]"));
        PayChannelEnum[] payChannelEnums = PayChannelEnum.values();
        for (PayChannelEnum payChannelEnum : payChannelEnums) {
            OrderPayListResponse orderPayListResponse = new OrderPayListResponse();
            orderPayListResponse.setPayType(payChannelEnum.name());
            orderPayListResponse.setPayInfo(payChannelEnum.getDescription());
            orderPayListResponse.setPayId(payChannelEnum.getCode());
            result.add(orderPayListResponse);
        }
        if (clientType.equals(ClientTypeEnum.H5_CLIENT.getCode())) {
            result = result.stream()
                    .filter(p -> p.getPayId().equals(PayChannelEnum.ALI_PAY_H5.getCode())
                            || p.getPayId().equals(PayChannelEnum.WX_PAY_H5.getCode())
                            || p.getPayId().equals(PayChannelEnum.BALANCE_PAY.getCode())).collect(Collectors.toList());
        } else if (clientType.equals(ClientTypeEnum.APPLETS_CLIENT.getCode())) {
            result = result.stream()
                    .filter(p -> p.getPayId().equals(PayChannelEnum.WX_PAY_LETS.getCode())
                            || p.getPayId().equals(PayChannelEnum.BALANCE_PAY.getCode())).collect(Collectors.toList());
        } else {
            result = result.stream()
                    .filter(p -> p.getPayId().equals(PayChannelEnum.ALI_PAY.getCode())
                            || p.getPayId().equals(PayChannelEnum.WX_PAY.getCode())
                            || p.getPayId().equals(PayChannelEnum.BALANCE_PAY.getCode())).collect(Collectors.toList());
        }
        result = result.stream().filter(p -> allowPayType.contains(p.getPayId().toString())).collect(Collectors.toList());
        responseResult.setData(result);
        return responseResult;
    }

    /**
     * 自动确认收货定时任务
     */
    @Scheduled(fixedDelay = 30 * 60 * 1000)
    public void scheduleConfirmReceipt() {
        QueryWrapper<UserOrder> userOrderQueryWrapper = new QueryWrapper<>();
        userOrderQueryWrapper.eq("order_status", OrderStatusEnum.READY_TO_RECEIVE.getCode())
                .isNotNull("confirm_time").le("confirm_time", new Date());
        List<UserOrder> userOrderList = userOrderMapper.selectList(userOrderQueryWrapper);
        if (userOrderList.isEmpty()) {
            return;
        }
        List<Integer> orderIds = userOrderList.stream().map(UserOrder::getId).collect(Collectors.toList());
        QueryWrapper<OrderGoods> orderGoodsQueryWrapper = new QueryWrapper<>();
        orderGoodsQueryWrapper.in("order_id", orderIds).between("goods_status", -1,1);
        List<OrderGoods> orderGoods = orderGoodsMapper.selectList(orderGoodsQueryWrapper);
        List<Integer> finalOrderIds = orderGoods.stream().map(OrderGoods::getOrderId).collect(Collectors.toList());
        userOrderList = userOrderList.stream().filter(u -> !finalOrderIds.contains(u.getId())).collect(Collectors.toList());
        for (UserOrder userOrder : userOrderList) {
            OrderInfoRequest request = new OrderInfoRequest();
            request.setOrderSn(userOrder.getOrderNo());
            request.setUid(userOrder.getBuyerId());
            try {
                confirmReceipt(request);
            } catch (Exception e) {
                log.error("自动确认收货出错 [{}]", e.getMessage());
            }
        }
    }

    /**
     * 即将确认收货提前24小时推送通知
     */
    @Scheduled(fixedDelay = 60 * 60 * 1000)
    public void scheduleWillAutoConfirmSendMessage() {
        QueryWrapper<UserOrder> userOrderQueryWrapper = new QueryWrapper<>();
        userOrderQueryWrapper.eq("order_status", OrderStatusEnum.READY_TO_RECEIVE.getCode())
                .isNotNull("confirm_time").le("confirm_time", DateUtil.getDateAfterDay(new Date(), 1));
        List<UserOrder> userOrderList = userOrderMapper.selectList(userOrderQueryWrapper);
        if (userOrderList.isEmpty()) {
            return;
        }
        List<Integer> orderIds = userOrderList.stream().map(UserOrder::getId).collect(Collectors.toList());
        QueryWrapper<OrderGoods> orderGoodsQueryWrapper = new QueryWrapper<>();
        orderGoodsQueryWrapper.in("order_id", orderIds).between("goods_status", -1,1);
        List<OrderGoods> orderGoods = orderGoodsMapper.selectList(orderGoodsQueryWrapper);
        List<Integer> finalOrderIds = orderGoods.stream().map(OrderGoods::getOrderId).collect(Collectors.toList());
        userOrderList = userOrderList.stream().filter(u -> !finalOrderIds.contains(u.getId())).collect(Collectors.toList());
        if (userOrderList.isEmpty()) {
            return;
        }
        Map<String, String> goodsCoverImgMap = goodsCoverImgMap(userOrderList.stream().map(UserOrder::getOrderNo).collect(Collectors.toList()));
        MessageTemplate messageTemplate = sendMessageHandler.getMessageTemplate(6);
        for (UserOrder userOrder : userOrderList) {
            Boolean result = redisTemplate.opsForValue().setIfAbsent("isAutoConfirmSendMessage::" + userOrder.getId(),
                    "自动确认收货前24小时推送通知已发送", 24, TimeUnit.HOURS);
            if (result) {
                String goodsCoverImg = "";
                if (goodsCoverImgMap.containsKey(userOrder.getOrderNo())) {
                    goodsCoverImg = goodsCoverImgMap.get(userOrder.getOrderNo());
                }
                String appMessageContent = messageTemplate == null ? "" : messageTemplate.getSmtAppContent();
                String stationMessageContent = messageTemplate == null ? "" : messageTemplate.getSmtMessageContent();
                sendMessageHandler.sendMessage(userOrder.getOrderNo(), appMessageContent, stationMessageContent,
                        "", "", "", goodsCoverImg, userOrder.getBuyerId(),
                        6, BigDecimal.ZERO, BigDecimal.ZERO, "", (byte) 0);
            }
        }
    }

    /**
     * 请求需要导入商品的所有图片
     *
     * @param orderNos
     * @return
     */
    public Map<String, String> goodsCoverImgMap(List<String> orderNos) {
        if (orderNos.isEmpty()) {
            return new HashMap<>();
        }
        QueryWrapper<OrderGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("order_no", orderNos).groupBy("order_no").orderByDesc("create_time");
        List<OrderGoods> list = orderGoodsMapper.selectList(queryWrapper);
        return list.stream().collect(Collectors.toMap(OrderGoods::getOrderNo, OrderGoods::getGoodsCoverImg));

    }


    /**
     * 客服系统调用 根据用户ID查询所有订单
     *
     * @param request
     * @return
     */
    @Override
    public TableDataInfo<KefuOrderResponse> kefuOrderListByBuyerId(KefuOrderRequest request) {
        TableDataInfo<KefuOrderResponse> tableDataInfo = new TableDataInfo<>();
        List<KefuOrderResponse> result = new ArrayList<>();
        QueryWrapper<UserOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("buyer_id", request.getMemberId());
        queryWrapper.orderByDesc("create_time");
        IPage<UserOrder> iPage = new Page<>(request.getPageNum(), request.getPageSize());
        IPage<UserOrder> records = userOrderMapper.selectPage(iPage, queryWrapper);
        List<UserOrder> userOrderList = records.getRecords();
        if (userOrderList.isEmpty()) {
            tableDataInfo.setTotal(0L);
            tableDataInfo.setRows(result);
            return tableDataInfo;
        }
        QueryWrapper<OrderGoods> orderGoodsQueryWrapper = new QueryWrapper<>();
        orderGoodsQueryWrapper.in("order_id", userOrderList.stream().map(UserOrder::getId).collect(Collectors.toList()));
        List<OrderGoods> orderGoodsList = orderGoodsMapper.selectList(orderGoodsQueryWrapper);
        Map<Integer, List<KefuOrderGoodsResponse>> map = new HashMap<>(userOrderList.size());
        for (OrderGoods orderGoods : orderGoodsList) {
            KefuOrderGoodsResponse kefuOrderGoodsResponse = new KefuOrderGoodsResponse();
            kefuOrderGoodsResponse.setGoods_image(orderGoods.getGoodsCoverImg());
            kefuOrderGoodsResponse.setGoods_name(orderGoods.getGoodsName());
            kefuOrderGoodsResponse.setGoods_num(orderGoods.getGoodsAmount());
            kefuOrderGoodsResponse.setGoods_price(orderGoods.getGoodsPrice());
            if (map.containsKey(orderGoods.getOrderId())) {
                map.get(orderGoods.getOrderId()).add(kefuOrderGoodsResponse);
                continue;
            }
            List<KefuOrderGoodsResponse> list = new ArrayList<>();
            list.add(kefuOrderGoodsResponse);
            map.put(orderGoods.getOrderId(), list);
        }
        for (UserOrder userOrder : userOrderList) {
            KefuOrderResponse kefuOrderResponse = new KefuOrderResponse();
            kefuOrderResponse.setAddress(userOrder.getReceiverAddress());
            kefuOrderResponse.setPhone(userOrder.getReceiverPhone());
            kefuOrderResponse.setTrue_name(userOrder.getReceiverName());
            kefuOrderResponse.setOrder_message(userOrder.getRemark());
            kefuOrderResponse.setAdd_time(userOrder.getCreateTime());
            kefuOrderResponse.setOrder_id(userOrder.getId());
            kefuOrderResponse.setOrder_sn(userOrder.getOrderNo());
            OrderStatusEnum orderStatusEnum = EnumUtil.getByCode(userOrder.getOrderStatus(), OrderStatusEnum.class);
            kefuOrderResponse.setOrder_state_str(orderStatusEnum.getMessage());
            if (map.containsKey(userOrder.getId())) {
                List<KefuOrderGoodsResponse> list = map.get(userOrder.getId());
                kefuOrderResponse.setGoods_list(list);
                kefuOrderResponse.setGoods_all_number(list.stream().mapToInt(KefuOrderGoodsResponse::getGoods_num).sum());
                kefuOrderResponse.setGoods_amount(list.stream().map(r -> r.getGoods_price().multiply(new BigDecimal(r.getGoods_num()))).reduce(BigDecimal.ZERO, BigDecimal::add).add(userOrder.getFreightFee()));
            }
            result.add(kefuOrderResponse);
        }
        tableDataInfo.setRows(result);
        tableDataInfo.setTotal(iPage.getTotal());
        return tableDataInfo;
    }
}
